using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using csammisrun.OscarLib.Utility;

namespace csammisrun.OscarLib
{
  /// <summary>
  /// A piece of data transmitted over a DirectIM connection
  /// </summary>
  public class Attachment
  {
    private byte[] _data = null;
    private int _id = 0;

    /// <summary>
    /// Initializes a new Attachment
    /// </summary>
    public Attachment(int id, byte[] data)
    {
      _id = id;
      _data = data;
    }

    /// <summary>
    /// Gets the ID of the attachment in the message
    /// </summary>
    public int ID
    {
      get { return _id; }
    }

    /// <summary>
    /// Gets a new <see cref="MemoryStream"/> consisting of the attachment data
    /// </summary>
    public MemoryStream Data
    {
      get
      {
        return new MemoryStream(_data, false);
      }
    }
  }

  /// <summary>
  /// An instant message sent via a direct connection
  /// </summary>
  public class DirectIM : IM
  {
    private DirectIMConnection _connection = null;
    private List<Attachment> _attachments = new List<Attachment>();

    /// <summary>
    /// Initializes a new Direct IM from a screenname
    /// </summary>
    internal DirectIM(string screenname, DirectIMConnection connection)
      : base(screenname)
    {
      _connection = connection;
    }

    /// <summary>
    /// Gets the connection that received the message
    /// </summary>
    internal DirectIMConnection Connection
    {
      get { return _connection; }
    }

    /// <summary>
    /// Gets the list of attachments received along with the message
    /// </summary>
    public List<Attachment> Attachments
    {
      get { return _attachments; }
    }
  }

  /// <summary>
  /// A generic instant message
  /// </summary>
  public class IM
  {
    #region Static methods
    /// <summary>
    /// Gets a <see cref="Encoding"/> from an instant messages charset and sub-charset arguments
    /// </summary>
    public static Encoding GetEncodingFromCharset(ushort charset, ushort subset)
    {
      // subset is actually ignored at the moment

      switch (charset)
      {
        case 0x0000:
          return Encoding.ASCII;
        case 0x0002:
          return Encoding.BigEndianUnicode;
        default:
          return Encoding.Default;
      }
    }
    #endregion

    protected string _screenname = "";
    protected UserInfo _userinfo = null;
    protected byte[] _icbmcookie = null;
    protected bool _isautoresponse = false;
    protected bool _wasreceivedoffline = false;
    protected Encoding _encoding = Encoding.Default;
    protected string _message = "";

    /// <summary>
    /// Initializes a new instant message from a screenname
    /// </summary>
    public IM(string screenname)
    {
      _screenname = screenname;
    }

    /// <summary>
    /// Initializes a new instant message received with a <see cref="UserInfo"/> block
    /// </summary>
    public IM(UserInfo userinfo)
    {
      _userinfo = userinfo;
      _screenname = userinfo.ScreenName;
    }

    #region Properties
    /// <summary>
    /// Gets the screenname that sent the message
    /// </summary>
    public string ScreenName
    {
      get { return _screenname; }
    }

    /// <summary>
    /// Gets the <see cref="UserInfo"/> block describing the message sender, if one exists
    /// </summary>
    public UserInfo SenderInfo
    {
      get { return _userinfo; }
    }

    /// <summary>
    /// Gets the unique cookie identifying this message
    /// </summary>
    public byte[] Cookie
    {
      get { return _icbmcookie; }
      internal set { _icbmcookie = value; }
    }

    /// <summary>
    /// Gets a value indicating whether or not this message is an auto response (away message)
    /// </summary>
    public bool IsAutoResponse
    {
      get { return _isautoresponse; }
      internal set { _isautoresponse = value; }
    }

    /// <summary>
    /// Gets a value indicating whether or not this message was received while offline and retrieved later
    /// </summary>
    public bool WasReceivedOffline
    {
      get { return _wasreceivedoffline; }
      internal set { _wasreceivedoffline = value; }
    }

    /// <summary>
    /// Gets the <see cref="Encoding"/> of the message
    /// </summary>
    public Encoding Encoding
    {
      get { return _encoding; }
      internal set { _encoding = value; }
    }

    /// <summary>
    /// Gets the message that has been received
    /// </summary>
    public string Message
    {
      get { return _message; }
      internal set { _message = value; }
    }
    #endregion
  }
}
